/** @file main.c
 *
 * @author cameris camerisdump@gmail.com
 */

#include "lcd.h"
#include "terminal.h"
#include "vtparser.h"
#include "process.h"
#include "uart.h"
#include "keyboard.h"
#include "profile.h"
#include "bell.h"
#include "working_timer.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/atomic.h>

/** @name button hardware settings
 * @{ */
#define BUTTON_PORT	PORTD
#define BUTTON_PIN	PIND
#define BUTTON_DDR	DDRD
#define BUTTON		PD5
/**@} */

volatile uint8_t button_state, button_press;

/** @brief debounce key press
 * @author _orginal by_ Peter Dannegger danni@specs.de */
void button_debounce(void)
{ /* {{{ */
	static uint8_t button_cnt;
	static uint8_t ct0, ct1;

	button_cnt++;
	if ((10/WTIMER_MS) <= button_cnt) {
		uint8_t i;
		i = button_state ^ ~BUTTON_PIN;
		ct0 = ~(ct0 & i);
		ct1 = ct0 ^ (ct1 & i);
		i &= ct0 & ct1;
		button_state ^= i;
		button_press |= button_state & i;
		button_cnt=0;
	}
} /* }}} */

/** @brief get pressed key
 * @param mask pin mask */
uint8_t button_get_press(uint8_t mask)
{ /* {{{ */
	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
		mask &= button_press;
		button_press ^= mask;
	}
	return mask;
} /* }}} */

int main(void) {
	uint8_t ch;
	uint16_t key;
	struct vtparse parser;

	BUTTON_PORT |= (1<<BUTTON);
	BUTTON_DDR &= ~(1<<BUTTON);

	lcd_init();
	term_init();

	uart_init();
	kbd_init();

	bell_init();

	wtimer_add(&button_debounce);

	wtimer_init();

	vtparse_init(&parser, process_callback);

	/*profile_load(0);*/
	profile_init();

	sei();

	kbd_init_after_sei();

	do {
		ch = uart_get_byte();
		if (uart_byte_is_valid()) {
			if ( term_get_show_control_chars() ) {
				process_show_control_chars(ch);
			} else {
				vtparse(&parser, ch);
			}
		}

		key = kbd_get_key();
		process_key(key);

		term_redraw_blink();

		if (button_get_press((1<<BUTTON))) {
			kbd_init();
			kbd_init_after_sei();
		}
	} while (1);
	return 0;
}

/* vim:set foldmethod=marker: */
